﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace System
{
    public static class StringHelper
    {
        static StringHelper()
        {
            List<char> cs = new List<char>(10);
            for (char i = char.MinValue; i < char.MaxValue; i++)
            {
                if (char.IsWhiteSpace(i))
                {
                    cs.Add(i);
                }
            }
            WhiteSpaces = cs.ToArray();
        }
        public static readonly char[] WhiteSpaces;

        public const char Space = ' ';
        /// <summary>
        /// 全角空格
        /// </summary>
        public static string FullWidthSpace
        {
            get { return "　"; }
        }

        /// <summary>
        /// 制表符
        /// </summary>
        public static string Tab
        {
            get { return "\t"; }
        }

        /// <summary>
        /// 换车符加换行符
        /// </summary>
        public static string NewLine
        {
            get { return "\r\n"; }
        }

        /// <summary>
        /// 回车符
        /// </summary>
        public static char EnterChar
        {
            get { return '\r'; }
        }

        /// <summary>
        /// 换行符
        /// </summary>
        public static char NewLineChar
        {
            get { return '\n'; }
        }


        /// <summary>
        /// 将数字转为其对应的中文表达形式
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string NumToChinese(int num)
        {
            var x = num.ToString();
            string[] pArrayNum = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
            //为数字位数建立一个位数组
            string[] pArrayDigit = { "", "十", "百", "千" };
            //为数字单位建立一个单位数组
            string[] pArrayUnits = { "", "万", "亿", "万亿" };
            var pStrReturnValue = ""; //返回值
            var finger = 0; //字符位置指针
            var pIntM = x.Length % 4; //取模
            int pIntK;
            if (pIntM > 0)
                pIntK = x.Length / 4 + 1;
            else
                pIntK = x.Length / 4;
            //外层循环,四位一组,每组最后加上单位: ",万亿,",",亿,",",万,"
            for (var i = pIntK; i > 0; i--)
            {
                var pIntL = 4;
                if (i == pIntK && pIntM != 0)
                    pIntL = pIntM;
                //得到一组四位数
                var four = x.Substring(finger, pIntL);
                var P_int_l = four.Length;
                //内层循环在该组中的每一位数上循环
                for (int j = 0; j < P_int_l; j++)
                {
                    //处理组中的每一位数加上所在的位
                    int n = Convert.ToInt32(four.Substring(j, 1));
                    if (n == 0)
                    {
                        if (j < P_int_l - 1 && Convert.ToInt32(four.Substring(j + 1, 1)) > 0 && !pStrReturnValue.EndsWith(pArrayNum[n]))
                            pStrReturnValue += pArrayNum[n];
                    }
                    else
                    {
                        if (!(n == 1 && (pStrReturnValue.EndsWith(pArrayNum[0]) | pStrReturnValue.Length == 0) && j == P_int_l - 2))
                            pStrReturnValue += pArrayNum[n];
                        pStrReturnValue += pArrayDigit[P_int_l - j - 1];
                    }
                }
                finger += pIntL;
                //每组最后加上一个单位:",万,",",亿," 等
                if (i < pIntK) //如果不是最高位的一组
                {
                    if (Convert.ToInt32(four) != 0)
                        //如果所有4位不全是0则加上单位",万,",",亿,"等
                        pStrReturnValue += pArrayUnits[i - 1];
                }
                else
                {
                    //处理最高位的一组,最后必须加上单位
                    pStrReturnValue += pArrayUnits[i - 1];
                }
            }
            return pStrReturnValue;
        }


        /// <summary>
        /// 还原字符的转义
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Unescape(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            Dictionary<string, string> dic = new Dictionary<string, string>() { { "\\", "\\\\" }, { "\n", "\\n" }, { "\r", "\\r" }, { " ", "\\s" }, { "\t", "\\t" }, { "\v", "\\v" }, { "\f", "\\f" }, { "\b", "\\b" }, { "\a", "\\a" } };
            foreach (var item in dic)
            {
                str = str.Replace(item.Value, item.Key);
            }

            //处理\x转义
            Regex regex1 = new Regex(@"(\\x[0-9A-Fa-f]{2})");
            var str1 = regex1.Replace(str, new MatchEvaluator(m =>
            {
                var v = m.Value;
                var val = Convert.ToByte(v.Substring(2, 2), 16);

                return $"{(char)val}";
            }));
            //处理\u转义
            Regex regex2 = new Regex(@"(\\u[0-9A-Fa-f]{4})");
            var str2 = regex2.Replace(str1, new MatchEvaluator(m =>
            {
                var v = m.Value;
                var b1 = Convert.ToByte(v.Substring(2, 2), 16);
                var b2 = Convert.ToByte(v.Substring(4, 2), 16);

                return Encoding.Unicode.GetString(new byte[] { b2, b1 });
            }));

            return str2;
        }
        /// <summary>
        /// 对字符进行转义
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Escape(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            Dictionary<string, string> dic = new Dictionary<string, string>() { { "\\", "\\\\" }, { "\n", "\\n" }, { "\r", "\\r" }, { " ", "\\s" }, { "\t", "\\t" }, { "\v", "\\v" }, { "\f", "\\f" }, { "\b", "\\b" }, { "\a", "\\a" } };
            foreach (var item in dic)
            {
                str = str.Replace(item.Key, item.Value);
            }

            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                if ((c >= 0 && c <= 32) || c == 127)
                {
                    var hex = Convert.ToString((int)c, 16);
                    if (hex.Length < 2)
                    {
                        hex = "0" + hex;
                    }
                    sb.Append("\\x").Append(hex);
                }
                else if ((c > 32 && c < 127))
                {
                    sb.Append(c);
                }
                else
                {
                    var data = Encoding.Unicode.GetBytes(c.ToString());
                    if (data.Length < 2)
                    {
                        data = new byte[] { data[0], 0 };
                    }
                    var hex1 = Convert.ToString(data[0], 16);
                    if (hex1.Length < 2)
                    {
                        hex1 = "0" + hex1;
                    }
                    var hex2 = Convert.ToString(data[1], 16);
                    if (hex2.Length < 2)
                    {
                        hex2 = "0" + hex2;
                    }
                    sb.Append($"\\u{hex2}{hex1}");
                }
                //else
                //{
                //    sb.Append(c);
                //}
            }

            return sb.ToString(); ;

        }


    }


}
